/*
 * log_thread.h
 *
 *  Created on: 2013-12-19
 *      Author: lixingyi
 */

#ifndef LOG_THREAD_H_
#define LOG_THREAD_H_

#include <vector>
#include <string>
#include <signal.h>
#include <memory>

#include "framework/thread.h"
#include "framework/circular_queue.h"
#include "framework/day_roll_logger.h"


enum
{
    LOG_NONE = 0 ,
    LOG_ERROR = 1 ,
    LOG_WARN = 2 ,
    LOG_INFO = 3 ,
    LOG_DEBUG = 4 ,

} ;

struct LogRecord
{
    LogRecord* next ;
    //LogRecord* prev;
    int16_t total_size ;
    int16_t data_size ;
    int8_t level ;
    char data[0] ;

} ;

class LogThread: public kingnet::simple_thread
{

public:
    LogThread();
    virtual ~LogThread();

public:
    void set_args(const char* log_prefix,int log_level) 
    {
        pthread_mutex_lock(&m_file_lock) ;

        m_prefix = log_prefix ;
        m_level = log_level >LOG_DEBUG ? LOG_DEBUG:log_level ;
        //invalidate current log file
        m_filedate = 0 ;

        pthread_mutex_unlock(&m_file_lock) ;
    }

    int write_log(int  log_level,const char* fmt,...) ;
    
protected:
    virtual int on_init() ;
    virtual void on_fini() ;
    virtual void run_once() ;

    void on_timer() ;

    int prepare() ;

    void flush_log(LogRecord* record) ;

private:
    pthread_cond_t m_cond ;
    pthread_mutex_t m_mutex ;
    pthread_mutex_t m_file_lock ;

    LogRecord* volatile m_head ;
    LogRecord* volatile m_tail;
    
    std::string m_prefix ;
    struct tm m_now ;
    int m_fd ;
    int m_filedate ;
    int m_level ;

    int m_last_time ;
    int m_reload_time ;


};


#ifdef NDEBUG
#define thread_write_log(logger,level,fmt,args...) \
    do{ logger->write_log(level,fmt,##args);} while(0)
#else
#define thread_write_log(logger,level, fmt,args...) \
    do{ logger->write_log(level,"[%s:%d]" fmt , __FILE__,__LINE__,##args);} while(0)
#endif


#define thread_error_log(logger, fmt ,args...) thread_write_log(logger,LOG_ERROR, fmt,##args)
#define thread_warn_log(logger, fmt ,args...) thread_write_log(logger,LOG_WARN, fmt,##args)
#define thread_info_log(logger, fmt ,args...) thread_write_log(logger,LOG_INFO, fmt,##args)


#ifdef NDEBUG
#define thread_debug_log(logger,fmt,args...)
#else
#define thread_debug_log(logger,fmt,args...) thread_write_log(logger,LOG_DEBUG,fmt,##args)
#endif


#endif /* LOG_THREAD_H_ */
